package org.geektimes.configuration.micro.config;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigBuilder;
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
import org.geektimes.configuration.micro.config.build.DefaultConfigBuilder;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultConfigProviderResolver extends ConfigProviderResolver {
    private ConcurrentHashMap<ClassLoader, Config> configsRepository = new ConcurrentHashMap<>();

    @Override
    public Config getConfig() {
        return getConfig(null);
    }

    @Override
    public Config getConfig(ClassLoader loader) {
        return configsRepository.computeIfAbsent(loader,this::newConfig);
    }

    protected Config newConfig(ClassLoader loader) {
        return this.newConfigBuilder(loader).build();
    }

    @Override
    public ConfigBuilder getBuilder() {
        return newConfigBuilder(null);
    }

    protected ConfigBuilder newConfigBuilder(ClassLoader classLoader) {
        return new DefaultConfigBuilder(resolveClassLoader(classLoader));
    }

    private ClassLoader resolveClassLoader(ClassLoader classLoader) {
        return null == classLoader ? this.getClass().getClassLoader(): classLoader;
    }

    @Override
    public void registerConfig(Config config, ClassLoader classLoader) {
        configsRepository.put(classLoader,config);
    }

    @Override
    public void releaseConfig(Config config) {
        List<ClassLoader> targetKeys = new LinkedList<>();
        configsRepository.forEach((k, v) -> {
            if (Objects.equals(config, v)) {
                targetKeys.add(k);
            }
        });
        targetKeys.forEach(configsRepository::remove);
    }
}
